--
-- Author: shunguo.chen
-- Date: 2018-12-03 10:48:23
--
-- TeamVo 队伍完整数据，包括：队伍基础信息、成员、聊天室Id，最后一次投票结果、招募信息
--

local Partner = require("app.public.dao.Partner")

local TeamRobotVo = import(".TeamRobotVo")
local TeamMemberInfoVo = import(".TeamMemberInfoVo")
local TeamRecruitInfoVo = import(".TeamRecruitInfoVo")

local fileName = string.getModeName(...)
local ClassRef = class(fileName)

-- 战队／团队 最大人数
local TEAM_MEMBER_MAX = 5
local LEGION_MEMBER_MAX = 10

-- 秘境得分str
local SECRET_GRADE_STRS = {
    L("lua_code_text_31"),
    L("ashes_trophy_gold"),
    L("ashes_trophy_silver"),
    L("ashes_trophy_bronze")
}

-- //队伍类型
-- enum TeamInfo_Type {
--     TEAMTYPE_NORMAL = 0; //普通队伍
--     TEAMTYPE_LEGION = 1; //军团队伍
-- }

-- //队伍状态
-- enum TeamInfo_State {
--     TEAMSTATE_NORMAL = 0; //普通状态
--     TEAMSTATE_BUSY   = 1; //忙碌状态(无法入队)
--     TEAMSTATE_BATTLE = 2; //战斗状态(无法入队)
--     TEAMSTATE_READYING  = 3; //战备中(无法入队)
-- }

-- //队伍信息
-- message TeamInfo {
--     string id                         = 1;//队伍ID
--     TeamInfo_Type type                = 2;//队伍类型(普通队伍 军团)
--     TeamInfo_State state              = 3;//队伍状态
--     repeated TeamMember teamMembers   = 4;//队伍成员
--     repeated TeamRobot robots         = 5;//机器人
--     RecruitInfo teamRecruitInfo         = 6;//队伍招募信息
--     int32 leaderLayer = 7; // 队长层数（用于秘境副本）
--     int32 grade = 8; // 当前层已获得最高评级（用于秘境副本）
--     repeated int32 npcStartBuffIds = 9; // 当前层随机到的npc buff(用于秘境副本:对应class_skill里的ID)
--     repeated int32 applyMembers    = 10;// 申请列表
-- }
function ClassRef:ctor(data)
    self._id = "" -- 队伍id
    self._type = 0 -- 队伍类型
    self._state = 0 -- 队伍状态

    self.members = {} -- 队伍成员列表
    self.recruitInfo = {} -- 队伍招募设置信息
    self.applyUids = {} -- 申请加入队伍的uid列表

    ---------------->>>>>> 本地缓存变量
    self._myMemberInfo = nil -- 自己的信息

    self._teamCombatPower = nil -- 队伍战斗力
    self._partners = {} -- 队长随从
    self._partnerDirty = true -- 队长随从有变化

    self._isCrossTeam = false -- 是否是跨服队伍
    self._isInCrossMatch = false -- 队伍是否在跨服匹配中

    if data then
        self:read(data)
    end
end

function ClassRef:read(data)
    self._id = data.id
    self._type = protobuf.enum_id("pb_team.TeamInfo_Type", data.type)
    self._state = protobuf.enum_id("pb_team.TeamInfo_State", data.state)
    self._leaderLayer = data.leaderLayer
    self._grade = data.grade
    self._npcStartBuffIds = data.npcStartBuffIds

    local applyUids = {}
    for i,uid in ipairs(data.applyMembers) do
        applyUids[i] = uid
    end
    self.applyUids = applyUids

    self:updateRobots( data.robots )
    self:updateTeamMemberListInfo( data.teamMembers )
    self:updateTeamRecruitInfoInfo( data.teamRecruitInfo )
end

function ClassRef:clear()
    self._id = "" -- 队伍id
    self._type = 0 -- 队伍类型
    self._state = 0 -- 队伍状态

    self.members = {} -- 队伍成员列表
    self._myMemberInfo = nil -- 自己的信息

    self.robots = {} -- 机器人

    self.recruitInfo = {} -- 队伍招募设置信息

    self.applyUids = {} -- 队伍招募设置信息

    self._teamCombatPower = nil -- 队伍战斗力
    self._partnerDirty = true

    self.teamTargetVo = nil

    self._isInCrossMatch = false -- 队伍是否在跨服匹配中
end

function ClassRef:setIsCrossTeam(b)
    self._isCrossTeam = b
end
function ClassRef:isCrossTeam()
    return self._isCrossTeam
end

function ClassRef:updateRobots(robots)
    self.robots = {}
    for i,robot in ipairs(robots) do
        self.robots[i] = TeamRobotVo.new(robot)
    end
end

-- 更新队伍成员列表信息
function ClassRef:updateTeamMemberListInfo( dataTemp )
    self.members = {}
    self._myMemberInfo = nil

    local myUid = UD:getUid()
    for i,v in ipairs( dataTemp ) do
        local eachMemberInfo = TeamMemberInfoVo.new( v )
        table.insert( self.members, eachMemberInfo )
        if eachMemberInfo:getUid() == myUid then
            self._myMemberInfo = eachMemberInfo
        end
    end
    assert( 0 < #self.members, " ------------->>>>>>>>> 队伍人数<=0？" )

    -- 队伍成员重新排序：队长在前、其他保持入队顺序
    -- 匹配时入队时间都是一样的，按等级降序-》uid升序
    table.sort(self.members, function(a, b)
        if a:isLeader() then
            return true
        elseif b:isLeader() then
            return false
        else
            if a.joinTeamStamp == b.joinTeamStamp then
                local aLv = a:getLv()
                local bLv = b:getLv()
                if aLv == bLv then
                    return a:getUid() < b:getUid()
                else
                    return aLv < bLv
                end
            else
                return a.joinTeamStamp < b.joinTeamStamp
            end
        end
    end)

    self._teamCombatPower = nil
    self._partnerDirty = true
end

-- 计算队伍总战斗力
function ClassRef:_calTeamTotalCombatPower()
    local total = 0
    for i, member in ipairs( self.members ) do
        total = total + member:getCapacity()
    end
    for i, robot in ipairs( self.robots ) do
        total = total + robot:getCombatPower()
    end
    self._teamCombatPower = total
end

-- 更新队伍招募设置信息
function ClassRef:updateTeamRecruitInfoInfo( dataTemp )
    self.recruitInfo = TeamRecruitInfoVo.new( dataTemp )
end

-- 是否申请过
function ClassRef:isApplied(uid)
    uid = uid or UD:getUid()
    return table.hasvalue(self.applyUids, uid)
end
function ClassRef:addApplyUid(uid)
    self.applyUids[#self.applyUids + 1] = uid
end

--------------------------------------------->>>>>>> 以下成员业务逻辑函数
-- 返回队长随从
function ClassRef:getLeaderPartnerInfo()    
    local leader = self.members[1]
    if leader:hasPartner() then
        if self._partnerDirty then
            self._partnerDirty = false
            local leaderInfo = leader.userBaseInfo
            local partners = leaderInfo.partners
            local newPs = {}
            for k ,v in pairs(partners) do
                local partner = Partner.new()
                partner:initWithBaseInfo(v)
                table.insert(newPs , partner)
            end
            self._partners = newPs
        end
    else
        self._partners = {}
    end
    return self._partners
end

-- 获得随从的战斗力，没有返回0
function ClassRef:getLeaderPartnerCapacity()
    local partners = self:getLeaderPartnerInfo()
    local f = 0
    for k ,v in pairs(partners) do
        f = f + v:getCombatPower()
    end
    return f
end

-- 队伍是否正常状态
function ClassRef:isTeamNormal()
    return 0 == self._state
end
-- 队伍是否繁忙状态
function ClassRef:isTeamBusy()
    return 1 == self._state
end
-- 队伍是否战斗状态
function ClassRef:isTeamBattle()
    return 2 == self._state
end
-- 队伍是否战备状态
function ClassRef:isTeamReadying()
    return 3 == self._state
end

-- 返回队伍总战力
-- withPartner 在队伍人数不足时算上队长随从的战斗力
function ClassRef:getTeamTotalCapacity(withPartner)
    if not self._teamCombatPower then
        self:_calTeamTotalCombatPower()
    end
    if withPartner then
        if self.teamTargetVo then
            local maxNum = self.teamTargetVo:getMaxNum()
            local isWithPartner = self.teamTargetVo:isWithPartner()
            if isWithPartner and #self.members < maxNum then
                return self._teamCombatPower + self:getLeaderPartnerCapacity()
            end
        else
            return self._teamCombatPower + self:getLeaderPartnerCapacity()
        end
    end
    return self._teamCombatPower
end

-- 平均战力(不计算随从)
function ClassRef:getTeamAverageCapacity()
    local total = self:getTeamTotalCapacity()
    local num = #self.members
    return math.ceil(total/num)
end

-- 返回队伍性质（队伍/军团）
function ClassRef:getTeamGrade()
    return self._type
end

function ClassRef:isCanChangeGrade()
    if self._type == 0 then
        return true, 1
    else
        if #self.members > TEAM_MEMBER_MAX then
            return false, L("lua_code_text_480")
        else
            return true, 0
        end
    end
end

-- 获取机器人列表
function ClassRef:getRobots()
    return self.robots
end

-- 获取机器人个数
function ClassRef:getRobotNum()
    return #self.robots
end

-- 获取队伍成员个数
function ClassRef:getMemberNum()
    return #self.members
end

-- uid是否队长
function ClassRef:isLeader( uid )
    if self._myMemberInfo and uid == self._myMemberInfo:getUid() then
        return self._myMemberInfo:isLeader()
    else
        local flag = false
        local memberTemp = self:getMember( uid )
        if memberTemp and memberTemp:isLeader() then
            flag = true
        end
        return flag
    end
end

-- 是否是"我"的队伍 我是队长
function ClassRef:isMyTeam()
    if self._myMemberInfo then
        return self._myMemberInfo:isLeader()
    else
        return false
    end
end

-- 是否满员
function ClassRef:isTeamFull()
    local isFull
    local tip

    local teamMemberNum = self:getMemberNum()
    local robotNum = self:getRobotNum()
    teamMemberNum = teamMemberNum + robotNum

    local teamMemberMaxNum = nil
    if 0 == self._type then -- 队伍
        teamMemberMaxNum = TEAM_MEMBER_MAX
        tip = L("tips_3000302")
    elseif 1 == self._type then -- 军团
        teamMemberMaxNum = LEGION_MEMBER_MAX
        tip = L("tips_3000301")
    else
        print( " -------->>>>>> 未知队伍类型 " )
    end
    if teamMemberNum < teamMemberMaxNum then
        isFull = false
        tip = nil
    else
        isFull = true
    end
    return isFull, tip
end


function ClassRef:getMaxPartnerNum()
    local isFull
    local tip

    local teamMemberNum = self:getMemberNum()
    local robotNum = self:getRobotNum()
    teamMemberNum = teamMemberNum + robotNum

    local teamMemberMaxNum = nil
    if 0 == self._type then -- 队伍
        teamMemberMaxNum = TEAM_MEMBER_MAX
        tip = L("tips_3000302")
    elseif 1 == self._type then -- 军团
        teamMemberMaxNum = LEGION_MEMBER_MAX
        tip = L("tips_3000301")
    else
        print( " -------->>>>>> 未知队伍类型 " )
    end

    return teamMemberMaxNum - teamMemberNum, true
end



-- 队伍是否是军团
function ClassRef:isLegion()
    return 1 == self._type
end

-- 队员最大数量
function ClassRef:getMemberMaxNum()
    return self._type == 1 and LEGION_MEMBER_MAX or TEAM_MEMBER_MAX
end

-- 返回队伍id
function ClassRef:getTeamId()
    return self._id
end

-- 返回队长uid
function ClassRef:getLeaderUid()
    return self.members[1]:getUid()
end
-- 返回队长名字
function ClassRef:getLeaderName()
    return self.members[1]:getName()
end

-- 获得队伍成员最小等级
function ClassRef:getMemberMinLv()
    local min = 10000
    for i,member in ipairs(self.members) do
        min = math.min(min, member:getLv())
    end
    return min
end

-- 获取uid对应成员
function ClassRef:getMember(uid)
    for i,member in ipairs( self.members ) do
        if member.userBaseInfo.uid == uid then
            return member
        end
    end
    return nil
end

-- 获取uid对应成员
function ClassRef:getRobot(uid)
    for i,robot in ipairs( self.robots ) do
        if robot:getUid() == uid then
            return robot
        end
    end
    return nil
end

function ClassRef:getLeader()
    return self.members[1]
end

-- 获取所有成员
function ClassRef:getMembers()
    return self.members
end

function ClassRef:getMemberBaseInfos()
    local baseInfos = {}
    for i,member in ipairs(self.members) do
        baseInfos[i] = member:getUserBaseInfo()
    end
    return baseInfos
end

-- 获取除"我"之外的队员
function ClassRef:getOtherMembers()
    local ret = {}
    for _, member in ipairs( self.members ) do
        if member.userBaseInfo.uid ~= UD.player.uid then
            ret[#ret + 1] = member
        end
    end
    return ret
end

-- 获取跟随队伍的成员个数
-- withRobot 是否计算机器人，机器人肯定是withTeam
function ClassRef:getWithTeamNum(withRobot)
    local memberNum = 0
    for _, member in ipairs( self.members ) do
        if member:isWithTeam() then
            memberNum = memberNum + 1
        end
    end
    if withRobot then
        memberNum = memberNum + #self.robots
    end
    return memberNum
end

-- 获取跟随队伍成员的平均等级
function ClassRef:getAverageTeamLevel()
    local totalLevel = 0
    local withTeamNums = 0
    for _, member in ipairs( self.members ) do
        if member:isWithTeam() then
            totalLevel = totalLevel + member.userBaseInfo.lv
            withTeamNums = withTeamNums + 1
        end
    end
    return math.ceil(totalLevel / withTeamNums)
end

-- 队伍中是否存在与"我"同工会的成员
function ClassRef:isHaveSameGuild()
    if UD:isInGuild() then -- 我在公会中？
        for _, member in ipairs( self.members ) do
            if not member:isMe() and member:isWithTeam() and member:getGuildId() == UD:getGuildId() then
                return true
            end
        end
    end
    return false
end

-- uid是否在队伍中
function ClassRef:isInTeam( uid )
    if uid < 0 then
        -- 是机器人
        local robot = self:getRobot(uid)
        return nil ~= robot
    else
        -- 真人队友
        local member = self:getMember( uid )
        return nil ~= member
    end
end

-- uid是否跟随队伍
function ClassRef:isWithTeam( uid )
    if self._myMemberInfo and uid == self._myMemberInfo:getUid() then
        return self._myMemberInfo:isWithTeam()
    else
        local isWithTeam = false
        local member = self:getMember( uid )
        if member then
            isWithTeam = member:isWithTeam()
        end

        -- 不是member，考虑是否是机器人
        if not isWithTeam and #self.robots > 0 then
            local robot = self:getRobot(uid)
            if robot then
                isWithTeam = true
            end
        end
        return isWithTeam
    end
end

-- 是否全员跟随队伍
function ClassRef:isAllWithTeam()
    -- 队长肯定是跟随状态
    for _, member in ipairs( self.members ) do
        if not member:isLeader() and not member:isWithTeam() then
            return false
        end
    end
    return true
end

-- 是否全员准备好， withTeam一定是ready状态
function ClassRef:isAllReady()
    -- 队长肯定是准备好的
    for _, member in ipairs( self.members ) do
        if not member:isLeader() and not(member:isReady() or member:isWithTeam()) then
            return false
        end
    end
    return true
end

-- 清空非跟随队员的ready状态
function ClassRef:clearAllReady()
    for _, member in ipairs( self.members ) do
        if not (member:isLeader() or member:isWithTeam()) then
            member:clearReady()
        end
    end
end

-- uid是否是否"暂离"
function ClassRef:isAwayFromTeam(uid)
    local member = self:getMember(uid)
    if member then
        return not member:isWithTeam()
    end
    return false
end

function ClassRef:getLvRangeStr()
    return self.recruitInfo.minLevel .. "-" .. self.recruitInfo.maxLevel
end

function ClassRef:getLeaderLayer()
    return self._leaderLayer
end

function ClassRef:getGrade()
    return self._grade
end

function ClassRef:getSecretGradeStr()
    return SECRET_GRADE_STRS[self._grade + 1]
end

function ClassRef:getNpcStartBuffIds()
    return self._npcStartBuffIds
end

-- 返回队伍的招募设置
function ClassRef:getTeamSetting()
    return self.recruitInfo
end

-- 返回队伍招募设置的拷贝
function ClassRef:getTeamSettingClone()
    return self.recruitInfo:clone()
end

-- 比较 tempRecruitInfo 是否与 self.recruitInfo 的数据段完全相等
function ClassRef:isTwoRecruitInfoEqual( tempRecruitInfo )
    return self.recruitInfo:isEqual( tempRecruitInfo )
end

--返回队伍目标ID
function ClassRef:getTeamTargetId()
    return self.recruitInfo:getTeamTargetId()
end

-- 队伍是否有目标
function ClassRef:hasTeamTarget()
    return self.recruitInfo:getTeamTargetId() > 0
end

-- 返回TeamTargetVo
function ClassRef:getTeamTargetVo()
    return self.teamTargetVo
end

function ClassRef:setTeamTargetVo(teamTargetVo, isOurTeam)
    self.teamTargetVo = teamTargetVo
    self.recruitInfo:setTeamTargetVo(teamTargetVo)
    if teamTargetVo and isOurTeam then
        teamTargetVo:setAutoRecruit(self.recruitInfo:isAutoRecruit())
    end
end

-- 设置是否跨服匹配中
function ClassRef:setIsInCrossMatch(b)
    self._isInCrossMatch = b
end
function ClassRef:isInCrossMatch()
    return self._isInCrossMatch
end

-- 是否需要申请才能进队
function ClassRef:isAutoApprove()
    return self.recruitInfo:isAutoApprove()
end

-- 是否对目标自动招募
function ClassRef:isAutoRecruit(targetId)
    if targetId then
        if targetId == self.recruitInfo:getTeamTargetId() then
            return self.recruitInfo:isAutoRecruit()
        else
            return false
        end
    else
        return self.recruitInfo:isAutoRecruit()
    end
end

--------------------------------------------->>>>>>>>>>>>>>>>>>>>> 以下成员辅助函数
function ClassRef:getMaxNumOfMembersByTeamGarde( garde )
    garde = garde or self:getTeamGrade()
    if 0 == garde then
        return TEAM_MEMBER_MAX
    elseif 1 == garde then
        return LEGION_MEMBER_MAX
    end
    return TEAM_MEMBER_MAX
end

return ClassRef